import $ from '$';


const dragNodeStyle = { width: '10px', height: '10px', position: 'absolute', background: '#0f68e4', boxSizing: 'border-box' }

type TSetEnable = (isImage: boolean, target?: HTMLImageElement) => void;

interface IScaleInfo {
  element: HTMLElement | null;             // 当前挂载指令元素
  image: HTMLImageElement | null;          // 点击的图片
  ratio: number;                           // 图片宽高比
  maxWidth: number;
  dragInfo: {                       
    image: HTMLImageElement | null;           // 拖动时透明的预览图片
    nodeList: HTMLDivElement[];               // 拖动按钮集合
  }
  setStatus: TSetEnable;                  // 设置拖动状态
}

const init = (el) => {
  const __setStatus: TSetEnable = (isImage, target?) => {
    if (isImage) {
      if (scaleInfo.image !== target) {
        scaleInfo.image = target!;

        /* 获取图片最大宽度 */
        let { offsetWidth } = scaleInfo.image;
        scaleInfo.image.style.width = '99999px';
        scaleInfo.maxWidth = scaleInfo.image.offsetWidth;
        scaleInfo.image.style.width = `${offsetWidth}px`;

        scaleInfo.image.style.outline = '3px solid #b4d7ff';

        scaleInfo.dragInfo.nodeList = Array.from(new Array(4), (i, idx) => $.element('div', {
          style: { ...dragNodeStyle, ...__calcPosition(idx) },
          attrs: { contenteditable: 'false' }, 
          className: 'cus__resize__dom',
          on: __dragEvents(idx)
        }));
        scaleInfo.dragInfo.image = __createPreviewImage(target);

        scaleInfo.ratio = scaleInfo.image.offsetWidth / scaleInfo.image.offsetHeight;

        [scaleInfo.dragInfo.image, ...scaleInfo.dragInfo.nodeList].map(node => scaleInfo.element?.appendChild(node));
      }
    } else {
      scaleInfo.image && (scaleInfo.image.style.outline = 'none');
      scaleInfo.dragInfo.image?.remove()
      scaleInfo.dragInfo.nodeList.map(dom => dom.remove());
      scaleInfo.dragInfo.nodeList = [];
      scaleInfo.image = null;
    }
  }
  let scaleInfo: IScaleInfo = {
    element: el,
    image: null,
    ratio: 0,
    maxWidth: 0,
    dragInfo: {
      image: null,
      nodeList: []
    },
    setStatus: __setStatus
  }
  el.style.position = 'relative';
  el.addEventListener('keydown', () => __setStatus(false))
  el.addEventListener('click', ({ target }) => !needToWait && scaleInfo.setStatus(target.tagName === 'IMG', target))

  let needToWait = false;

  const __dragEvents = (idx) => {
    return {
      mousedown: (event: MouseEvent) => {
        event.stopPropagation();
        event.preventDefault();

        let { clientX, clientY } = event;

        let previewImage = scaleInfo.dragInfo.image!;
        previewImage.style.opacity = '.5'
        previewImage.style.borderColor = '#999';
        previewImage.style.width = `${scaleInfo.image!.offsetWidth}px`;
        previewImage.style.height = `${scaleInfo.image!.offsetHeight}px`;
        previewImage.style.top = `${scaleInfo.image!.offsetTop}px`;
        previewImage.style.left = `${scaleInfo.image!.offsetLeft}px`;

        let { offsetWidth, offsetHeight, offsetLeft, offsetTop } = scaleInfo.image!;

        document.onmousemove = (e: MouseEvent) => {

          let x = e.clientX - clientX;
          let y = e.clientY - clientY;
          let ratio = scaleInfo.ratio;
          let xGy = Math.abs(x) > Math.abs(y) * ratio;
          if (idx === 0) {
            /* 根据宽高比 计算拖动大小 */
            let moveX = xGy ? x : y * ratio;
            let moveY = xGy ? x / ratio : y;

            previewImage.style.width = `${offsetWidth - moveX}px`;
            previewImage.style.height = `${offsetHeight - moveY}px`;
            previewImage.style.left = `${offsetLeft + moveX}px`;
            previewImage.style.top = `${offsetTop + moveY}px`;
          } else if (idx === 1) {
            /* 根据宽高比 计算拖动大小 */
            let moveX = xGy ? x : -(y * ratio);
            let moveY = xGy ? x / ratio : -y;

            previewImage.style.width = `${offsetWidth + moveX}px`;
            previewImage.style.height = `${offsetHeight + moveY}px`;
            previewImage.style.top = `${offsetTop - moveY}px`;
          } else if (idx === 2) {
            let moveX = xGy ? -x : y * ratio;
            let moveY = xGy ? -x / ratio : y;

            previewImage.style.width = `${offsetWidth + moveX}px`;
            previewImage.style.height = `${offsetHeight + moveY}px`;
            previewImage.style.left = `${offsetLeft - moveX}px`;
          } else {
            let moveX = xGy ? x : y * ratio;
            let moveY = xGy ? x / ratio : y;

            previewImage.style.width = `${offsetWidth + moveX}px`;
            previewImage.style.height = `${offsetHeight + moveY}px`;
          }
        }
        document.onmouseup = (e: MouseEvent) => {
          let previewImage = scaleInfo.dragInfo.image!;
          let { offsetWidth, offsetHeight } = previewImage;
          scaleInfo.image!.style.width = `${offsetWidth > scaleInfo.maxWidth ? scaleInfo.maxWidth : offsetWidth}px`;
          scaleInfo.image!.style.height = offsetHeight > scaleInfo.maxWidth / scaleInfo.ratio ? `${scaleInfo.maxWidth / scaleInfo.ratio}px` : `${offsetHeight}px`;

          scaleInfo.dragInfo.image!.style.opacity = '0';
          scaleInfo.dragInfo.image!.style.borderColor = 'transparent';
          scaleInfo.dragInfo.nodeList.map((node, idx) => {
            Object.keys(__calcPosition(idx)).map(key => node.style[key] = __calcPosition(idx)[key])
          })

          document.onmousemove = null;
          document.onmouseup = null;
          needToWait = true;
          setTimeout(() => needToWait = false);
        }
      }
    }
  }


  const __calcPosition = (idx) => {
    let { offsetWidth, offsetHeight, offsetTop, offsetLeft } = scaleInfo.image!;
    if (idx === 0) {
      return {
        top: `${offsetTop}px`,
        left: `${offsetLeft}px`,
        transform: 'translate3d(-50%, -50%, 0)',
        cursor: 'nw-resize'
      }
    } else if (idx === 1) {
      return {
        top: `${offsetTop}px`,
        left: `${offsetLeft + offsetWidth}px`,
        transform: 'translate3d(-50%, -50%, 0)',
        cursor: 'ne-resize'
      }
    } else if (idx === 2) {
      return {
        top: `${offsetTop + offsetHeight}px`,
        left: `${offsetLeft}px`,
        transform: 'translate3d(-50%, -50%, 0)',
        cursor: 'sw-resize'
      }
    } else {
      return {
        top: `${offsetTop + offsetHeight}px`,
        left: `${offsetLeft + offsetWidth}px`,
        transform: 'translate3d(-50%, -50%, 0)',
        cursor: 'se-resize'
      }
    }
  }


}

export default {
  name: 'resize',
  mounted: init,
  updated: init,
}


const __createPreviewImage = (target) => $.element('img', {
  attrs: { src: target.src }, className: 'cus__resize__dom', style: {
    width: `${target.offsetWidth}px`,
    height: `${target.offsetHeight}px`,
    border: 'dashed 1px transparent',
    boxSizing: 'content-box',
    pointerEvents: 'none',
    position: 'absolute',
    top: `${target.offsetTop - 1}px`,
    left: `${target.offsetLeft - 1}px`,
    opacity: '0'
  }
})